# -*- coding: utf-8 -*-
import json
import logging
import math
import time
from datetime import datetime
from traceback import format_exc

import requests
from requests import TooManyRedirects
from urllib3.exceptions import MaxRetryError, SSLError

from zc_core.middlewares.proxies.proxy_facade import ProxyFacade
from zc_core.model.items import OrderItem
from zc_core.util.batch_gen import time_to_batch_no
from zc_core.util.common import parse_timestamp
from zc_core.util.encrypt_util import md5, build_sha1_order_id
from zc_core.util.order_deadline_filter import OrderItemFilter

from ctaxccgp.simple.cookie_pool import CookiePool
from ctaxccgp.simple.simple_dao import SimpleDao
from ctaxccgp.simple.token_queue import TokenQueue


class OrderCrawler(object):
    total_page = None
    page_size = 10

    bind_count = 0
    max_bind_count = 2
    order_api_tpl = 'https://ctaxccgp.zcygov.cn/front/detail/item/dealRecord?itemId={}&pageSize=10&pageNo={}&timestamp={}'

    dao = SimpleDao()
    cookie_pool = CookiePool()
    proxy_facade = ProxyFacade()
    order_filter = OrderItemFilter()
    token_queue = TokenQueue()

    def __init__(self, sku, *args, **kwargs):
        super(OrderCrawler, self).__init__(*args, **kwargs)
        self.sku_id = sku.get('_id')
        self.sp_id = sku.get('supplierId')

    def run(self):
        return self.pagination(1)

    def pagination(self, page):
        txt = self.send_req(page)
        if txt:
            has_next, total = self.parse_order(txt, page)
            if has_next and total and self.total_page is None:
                self.total_page = int(math.ceil(total / self.page_size))
            if has_next and self.total_page and self.total_page > 1:
                for next_page in range(2, self.total_page):
                    self.pagination(next_page)

    def send_req(self, page):
        token = self.token_queue.pop()
        if token:
            # proxy = '114.99.220.185:4217'
            proxy = self.proxy_facade.get_proxy()
            logging.info('采集: sku=%s, page=%s' % (self.sku_id, page))
            try:
                rs = requests.get(
                    url=self.order_api_tpl.format(self.sku_id, page, int(time.time())),
                    cookies=self.cookie_pool.get_cookies(),
                    headers={
                        'Connection': 'keep-alive',
                        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36',
                        'Accept': 'application/json, text/plain, */*',
                        'Referer': 'https://ctaxccgp.zcygov.cn/items/{}?searchType=1'.format(self.sku_id),
                        'aliyunValidateParam': token,
                    },
                    proxies={
                        "https": "http://{}".format(proxy),
                    },
                    timeout=45,
                )
                return rs.text
            except TooManyRedirects as ex:
                logging.info('--> logout: %s' % time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
                self.cookie_pool.clean_cookies()
            except Exception as e:
                if isinstance(e, (MaxRetryError, requests.exceptions.ProxyError, SSLError, TimeoutError, ConnectionRefusedError, IOError)):
                    self.proxy_facade.mark_fail(proxy)
                else:
                    print(format_exc())
                return self.send_req(page)

    def parse_order(self, txt, page):
        has_next = True
        total = 0
        order_list = list()
        prev_order = None
        same_order_no = 1
        js = json.loads(txt)
        if not js or not js.get('success'):
            logging.info('反爬: sku=%s, page=%s, err=%s' % (self.sku_id, page, txt))
        else:
            js_data = js.get('result', {}).get('orderItemDealRecordDtoPaging', {})
            rows = js_data.get('data', [])
            total = js_data.get('total', 0)
            for row in rows:
                order = OrderItem()
                order['skuId'] = self.sku_id
                # 采购时间  1574840734000
                order_timestamp = row.get('dealDate')
                order_time = parse_timestamp(order_timestamp)
                # 采集截止
                if self.order_filter.to_save(order_time):
                    order['count'] = row.get('dealCount')
                    order['amount'] = row.get('dealTotalPrice') / 100
                    order['orderDept'] = row.get('purchaseOrgName')
                    order['deptId'] = md5(row.get('purchaseOrgName'))
                    order['supplierId'] = self.sp_id
                    order['orderTime'] = order_time
                    order['batchNo'] = time_to_batch_no(order_time)
                    order['genTime'] = datetime.utcnow()
                    if prev_order and prev_order.equals(order):
                        same_order_no = same_order_no + 1
                    else:
                        same_order_no = 1
                    addition = {
                        'sameOrderNo': same_order_no,
                        'orderTimeStr': order_timestamp,
                    }
                    sha1_id = build_sha1_order_id(order, addition)
                    order['id'] = sha1_id
                    order['orderId'] = sha1_id
                    order_list.append(order)
                    prev_order = order
                else:
                    has_next = False

        if order_list:
            self.dao.save_orders(order_list)
            logging.info('订单: sku=%s, page=%s, cnt=%s' % (self.sku_id, page, len(order_list)))
        else:
            logging.info('无单: sku=%s, page=%s' % (self.sku_id, page))

        return has_next, total
